package com.ruoyi.common.service.business.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.util.WxMaConfigHolder;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.config.WxMaProperties;
import com.ruoyi.common.core.domain.BaseEntity;
import com.ruoyi.common.core.domain.entity.AppWxParam;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.pagination.PageInfo;
import com.ruoyi.common.core.pagination.Paging;
import com.ruoyi.common.domain.business.mp.MpUser;
import com.ruoyi.common.dto.LoginDTO;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.mapper.business.MpUserMapper;
import com.ruoyi.common.param.DelearParam;
import com.ruoyi.common.param.user.MpUserPageParam;
import com.ruoyi.common.service.business.MpUserService;
import com.ruoyi.common.service.system.ISysDeptService;
import com.ruoyi.common.utils.PasswordUtil;
import com.ruoyi.common.utils.SaltUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.satoken.StpWxUtils;
import com.ruoyi.common.utils.u9.U9Utils;
import com.ruoyi.common.vo.business.LoginWxVo;
import com.ruoyi.common.vo.business.MpUserVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Song
 * @date 2024/10/15 9:23
 * @description
 */
@Service
@Slf4j
public class MpUserServiceImpl extends ServiceImpl<MpUserMapper, MpUser> implements MpUserService {
    @Autowired
    private WxMaService wxMaService;
    @Autowired
    private WxMaProperties wxMaProperties;
    @Autowired
    private MpUserService mpUserService;
    @Autowired
    private ISysDeptService deptService;
    @Autowired
    private U9Utils u9Utils;

    @Override
    public LoginWxVo loginWx(AppWxParam appWxParam) {
        if (StringUtils.isNotBlank(appWxParam.getUsername())&&StringUtils.isNotBlank(appWxParam.getPassword())){
            u9Utils.getUserInfo();
            //TODO u9获取组织架构
            MpUser user = new MpUser();
            MpUser one = getOne(new LambdaQueryWrapper<MpUser>().eq(MpUser::getUsername, ""));
            String salt="";
            String password="";
            if (one!=null){
                BeanUtil.copyProperties(one,user);
            }else {
                salt = SaltUtil.generateSalt();
                user.setUsername("");
                user.setSalt(salt);
                password = PasswordUtil.encrypt("123456", salt);
                user.setPassword(password);
            }
            saveOrUpdate(user);
        }
        LoginWxVo loginWxVo = new LoginWxVo();
        String appId = wxMaProperties.getConfigs().get(0).getAppid();
        if (StringUtils.isBlank(appWxParam.getCode())) {
            throw new ServiceException("empty code");
        } else if (!this.wxMaService.switchover(appId)) {
            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置，请核实！", appId));
        } else {
            try {
                WxMaJscode2SessionResult result = this.wxMaService.getUserService().getSessionInfo(appWxParam.getCode());
                MpUser user = null;
                user = this.getOne(new LambdaQueryWrapper<MpUser>().eq(MpUser::getOpenId, result.getOpenid()));
                if (user != null) {
                    if (StringUtils.isBlank(user.getOpenId())) {
                        MpUser updateBean = new MpUser();
                        updateBean.setId(user.getId());
                        updateBean.setOpenId(result.getOpenid());
                        this.updateById(updateBean);
                    }
                    StpWxUtils.login(user.getId());
                } else {
                    if (StringUtils.isBlank(appWxParam.getUsername())||StringUtils.isBlank(appWxParam.getPassword())){
                        throw new ServiceException("请输入账号密码登录",1010);
                    }
                    MpUser mpUser = mpUserService.getOne(new LambdaQueryWrapper<MpUser>().eq(MpUser::getUsername, appWxParam.getUsername()));
                    String userInfoStr = StringEscapeUtils.unescapeHtml4(appWxParam.getUserInfo());
                    JSONObject userInfo = JSONUtil.parseObj(userInfoStr);
                    MpUser bean = new MpUser();
                    if (mpUser!=null){
                        String encrypt = PasswordUtil.encrypt(appWxParam.getPassword(), mpUser.getSalt());
                        if (!encrypt.equals(mpUser.getPassword())){
                            throw new ServiceException("密码错误",401);
                        }
                        bean.setId(mpUser.getId());
                    }else {
                        bean.setUsername(appWxParam.getUsername());
                        String salt=SaltUtil.generateSalt().toLowerCase();
                        bean.setSalt(salt);
                        bean.setPassword(SaltUtil.getSalt(appWxParam.getPassword(),salt));
                    }
                    bean.setNickName(userInfo.getStr("nickName"));
                    bean.setOpenId(result.getOpenid());
                    this.saveOrUpdate(bean);
                    StpWxUtils.login(bean.getId());
                }
            } catch (Exception var10) {
                log.info("微信小程序登录异常：{}", var10.getMessage());
            } finally {
                WxMaConfigHolder.remove();
            }
        }
        return loginWxVo;
    }

    public void changePwd(LoginDTO loginDTO) {
        MpUser user = getOne(new LambdaQueryWrapper<MpUser>().eq(MpUser::getUsername, loginDTO.getUsername()).eq(MpUser::getId,StpWxUtils.getLoginId()));
        if (user==null){
            throw new ServiceException("当前登录授权登录微信非修改账号绑定微信。");
        }
        String encrypt = PasswordUtil.encrypt(loginDTO.getNewPassword(), user.getSalt());
        if (encrypt.equals(user.getPassword())){
            throw new ServiceException("新旧密码不可相同");
        }
        user.setPassword(encrypt);
        updateById(user);
    }

    public void checkPwdIsDefault(LoginDTO loginDTO) {
        if (loginDTO.getOldPassword().equals("123456")){
            throw new ServiceException("请修改密码");
        }
        MpUser user = getById(Long.parseLong(StpWxUtils.getLoginId().toString()));
        if (user==null){
            throw new ServiceException("当前登录授权登录微信未绑定账号");
        }
    }

    public Paging<MpUserVo> pageVo(MpUserPageParam pageParam) {
        LambdaQueryWrapper<MpUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(BaseEntity::getCreateTime);
        if (pageParam.getPhone()!=null){
            wrapper.and(w->{
                w.eq(MpUser::getPhone,pageParam.getPhone());
            });
        }
        if (StringUtils.isNotBlank(pageParam.getUsername())){
            wrapper.and(w->{w.like(MpUser::getUsername,pageParam.getUsername());
            });
        }
        if (StringUtils.isNotBlank(pageParam.getNickName())){
            wrapper.and(w->{w.like(MpUser::getNickName,pageParam.getNickName());});
        }
        if (pageParam.getDeptId()!=null){
            List<SysDept> depts = deptService.list(new LambdaQueryWrapper<SysDept>().apply("find_in_set("+pageParam.getDeptId()+", ancestors) ").eq(SysDept::getDelFlag,"0"));
            List<Long> deptIds = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList());
            wrapper.and(w->{
                w.eq(MpUser::getDeptId,pageParam.getDeptId()).or().in(CollectionUtil.isNotEmpty(deptIds),MpUser::getDeptId,deptIds);
            });
        }
        Page<MpUser> pageInfo = new PageInfo<>(pageParam);
        IPage<MpUser> page = this.page(pageInfo, wrapper);
        IPage<MpUserVo> convert = page.convert(item -> {
            MpUserVo vo = new MpUserVo();
            if (vo.getDeptId()!=null){
                SysDept dept = deptService.getById(vo.getDeptId());
                vo.setDeptName(dept.getDeptName());
            }
            return vo;
        });
        return new Paging<>(convert);
    }

    public MpUserVo pageDelear(DelearParam delearParam) {
        //TODO
        return null;
    }
}
